from Abstract import Instruction
class Random (Instruction):
	Token = 'random'
# ----------------------------------------------------------------------------

class Persist (Instruction):
	Token = 'persist'
# ----------------------------------------------------------------------------

class Direction (Instruction):
	from Arguments import Interface
	Children = (Interface,)
# ----------------------------------------------------------------------------

class Inbound (Direction):
	Token = 'in'
# ----------------------------------------------------------------------------

class Outbound (Direction):
	Token = 'out'
# ----------------------------------------------------------------------------

class IPv4_and_Ports (Instruction):
	from Arguments import IPv4, Ports
	Children = (IPv4, Ports)

	def check (self):
		if not self.child (self.IPv4) and not self.child (self.Ports):
			self.fail_check ("'%s' instruction requires either '%s' or '%s' argument, or both" % (self.Token, self.IPv4.Token, self.Ports.Token))
# ----------------------------------------------------------------------------

class Source (IPv4_and_Ports):
	Token = 'src'
# ----------------------------------------------------------------------------

class Destination (IPv4_and_Ports):
	Token = 'dst'
# ----------------------------------------------------------------------------

class Rewrite_Spec (IPv4_and_Ports):
	Token = 'new'
	from Arguments import IPv4, Ports
	Children = (IPv4, Ports, Random, Persist)

	def check (self):
		super (Rewrite_Spec, self).check ()
		Addr = self.child (self.IPv4)
		Ports = self.child (self.Ports)
		if Addr:
			if Addr.Invert:
				self.fail_check ("'%s' instruction can not accept a negated address" % self.Token)
			if len (Addr.Values) > 1:
				self.fail_check ("'%s' instruction can not accept a list of addresses" % self.Token)
			Value, = Addr.Values
			if '..' not in Value and '/' not in Value and Value != '(myself)' and not self.IPv4.is_dotted_quad (Value):
				self.fail_check ("'%s' instruction requires an address to be a dotted quad or an address/prefix or an IP range, not '%s'" % (self.Token, Value))
			if '(myself)' in Addr.Values and self.child (Persist):
				self.fail_check ("'%s' instruction can not accept '%s' flag with '(myself)' address" % (self.Token, Persist.Token))
		if Ports:
			if Ports.Invert:
				self.fail_check ("'%s' instruction can not accept negated ports" % self.Token)
			if len (Ports.Values) > 1:
				self.fail_check ("'%s' instruction can not accept a list of ports" % self.Token)
		else:
			if self.child (Random):
				self.fail_check ("'%s' instruction can not accept '%s' flag without ports" % (self.Token, Random.Token))
# ----------------------------------------------------------------------------
